package pers.cj.pdos.controller;


import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.BaseRowModel;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import pers.cj.pdos.controller.base.BaseController;
import pers.cj.pdos.controller.entity.ResponseData;
import pers.cj.pdos.controller.entity.ResponseEntity;
import pers.cj.pdos.controller.entity.ResponseList;
import pers.cj.pdos.entity.*;
import pers.cj.pdos.excel.ExcelInGoods;
import pers.cj.pdos.excel.ExcelInGoodsOrder;
import pers.cj.pdos.service.*;
import pers.cj.pdos.task.CleanTempExcelTask;
import pers.cj.pdos.utils.*;
import pers.cj.pdos.vo.*;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author chenj
 * @since 2019-11-04
 */
@Controller
@RequestMapping("/inGoods")
public class InGoodsController extends BaseController {
    @Autowired
    IInGoodsService inGoodsService;
    @Autowired
    IHouseInService houseInService;
    @Autowired
    IHouseInGoodsService houseInGoodsService;
    @Autowired
    IGoodsStockService goodsStockService;

    @RequiresPermissions("inGoods:query")
    @RequestMapping("/inGoods")
    public String inGoods(Model model) {
        model.addAttribute(getBusinessSet());
        return "inGoods/inGoods";
    }

    @RequiresPermissions("inGoods:insert")
    @RequestMapping("/inGoodsNew")
    public String inGoodsNew(){
        return "/inGoods/inGoodsNew";
    }

    @RequiresPermissions("inGoods:insert")
    @RequestMapping("/inGoodsNewByInGoodsOrder")
    public String inGoodsNewByInGoodsOrder(Model model, String inGoodsOrderId){
        model.addAttribute("inGoodsOrderId", inGoodsOrderId);
        return "/inGoods/inGoodsNewByInGoodsOrder";
    }

    @RequiresPermissions("inGoods:insert")
    @RequestMapping("/inGoodsNewByBorrowIn")
    public String inGoodsNewByBorrowIn(Model model, String borrowInId){
        model.addAttribute("borrowInId", borrowInId);
        return "/inGoods/inGoodsNewByBorrowIn";
    }

    @RequiresPermissions("inGoods:query")
    @RequestMapping("/inGoodsDetail")
    public String inGoodsDetail(Model model, String id){
        model.addAttribute("id",id);
        return "/inGoods/inGoodsDetail";
    }

    @ResponseBody
    @RequestMapping("/inGoods/getListForSelect")
    public ResponseList getListForSelect(int page, int limit, String search){
        Company company = getCompany();
        UserVo userVo = getLoginUserVo();

        List<InGoodsVo> list = inGoodsService.listVoForSelect(company.getId(),
                page,
                limit,
                null,
                PdosUtils.getViewOrderStoreId(userVo,null),
                PdosUtils.getViewOrderUserId(userVo,null),
                Utils.genLikeData(search));
        long count = inGoodsService.countForSelect(company.getId(),
                null,
                PdosUtils.getViewOrderStoreId(userVo,null),
                PdosUtils.getViewOrderUserId(userVo,null),
                Utils.genLikeData(search));
        return ResponseList.success(count,list);
    }

    @ResponseBody
    @RequestMapping("/inGoods/getList")
    public ResponseList getList(int page,
                                int limit,
                                String close,
                                String search,
                                String no,
                                String goodsName,
                                String remark,
                                String provider,
                                String makeTime1,
                                String makeTime2,
                                String storeId,
                                String userId,
                                String date1,
                                String date2,
                                String date,
                                String providerId,
                                String houseId,
                                String makeUserId){
        Company company = getCompany();
        UserVo userVo = getLoginUserVo();

        List<InGoodsVo> list = inGoodsService.listVo(company.getId(),
                page,
                limit,
                Utils.genBoolean(close),
                Utils.genLikeData(search),
                Utils.genLikeData(no),
                Utils.genLikeData(goodsName),
                Utils.genLikeData(remark),
                Utils.genLikeData(provider),
                Utils.genDate(makeTime1),
                Utils.genDate(makeTime2),
                storeId,
                PdosUtils.getViewOrderStoreId(userVo,null),
                PdosUtils.getViewOrderUserId(userVo,userId),
                Utils.genDate(date1),
                Utils.genDate(date2),
                Utils.genDate(date),
                providerId,
                houseId,
                makeUserId);
        long count = inGoodsService.count(company.getId(),
                Utils.genBoolean(close),
                Utils.genLikeData(search),
                Utils.genLikeData(no),
                Utils.genLikeData(goodsName),
                Utils.genLikeData(remark),
                Utils.genLikeData(provider),
                Utils.genDate(makeTime1),
                Utils.genDate(makeTime2),
                storeId,
                PdosUtils.getViewOrderStoreId(userVo,null),
                PdosUtils.getViewOrderUserId(userVo,userId),
                Utils.genDate(date1),
                Utils.genDate(date2),
                Utils.genDate(date),
                providerId,
                houseId,
                makeUserId);
        return ResponseList.success(count,list);
    }

    @ResponseBody
    @RequiresPermissions("inGoods:insert")
    @RequestMapping("/inGoods/add")
    public ResponseEntity add(@RequestBody InGoodsVo inGoodsVo){

        Company company = getCompany();
        BusinessSet businessSet = getBusinessSet();

        if (Utils.isEmpty(inGoodsVo.getNo())){
            return ResponseEntity.fail("编号不能为空");
        }

        if (Utils.isEmpty(inGoodsVo.getInGoodsGoodsVoList())){
            return ResponseEntity.fail("您未选择任何商品");
        }

        if (inGoodsVo.getDate() == null){
            return ResponseEntity.fail("业务日期不能为空");
        }

        if (inGoodsVo.getTotalAmt().compareTo(inGoodsVo.getRealAmt()) == -1){
            return ResponseEntity.fail("应付金额不能大于总计金额");
        }

        if (inGoodsService.checkNo(inGoodsVo.getNo(),company.getId())){
            return ResponseEntity.fail("编号已被使用");
        }

        if (getHouseLocking(inGoodsVo.getHouseId())) {
            return ResponseEntity.fail("仓库被锁定，请更换仓库");
        }

        GoodsUtil goodsUtil = new GoodsUtil(inGoodsVo.getHouseId(),inGoodsVo.getInGoodsGoodsVoList(),null);

        InGoods inGoods = DataUtil.genEntityFromVo(InGoods.class,inGoodsVo);
        DataUtil.processEntity(company,inGoods);
        inGoods.setClose(false);
        inGoods.setRefund(0);
        inGoods.setMakeUserId(getLoginUserId());
        inGoods.setMakeTime(new Date());
        if (Utils.isEmpty(inGoods.getInGoodsOrderId())){
            inGoods.setInGoodsOrderId(null);
        }
        if (!PdosUtils.houseInOut(businessSet)) {
            inGoods.setStatus(1);
        } else {
            inGoods.setStatus(2);
        }

        inGoods.setOldTotalAmt(goodsUtil.getTotalAmount());

        if(!PdosUtils.inTaxRateFlag(businessSet)) {
            inGoods.setTax(new BigDecimal(0));
        } else {
            inGoods.setTax(inGoods.getOldTotalAmt().multiply(PdosUtils.inTaxRate(businessSet)));
        }


        List<InGoodsGoods> inGoodsGoodsList = new ArrayList<>();
        List<GoodsSn> goodsSnList = new ArrayList<>();
        List<GoodsSnLog> goodsSnLogList = new ArrayList<>();
        Map<String,Object> snInitMap = new HashMap<>();
        snInitMap.put("inDate", new Date());//设置入库日期
        snInitMap.put("status", 1);//设置状态为未出库
        for (InGoodsGoodsVo vo:inGoodsVo.getInGoodsGoodsVoList()) {
            InGoodsGoods entity = DataUtil.genEntityFromVo(InGoodsGoods.class, vo);
            DataUtil.processEntity(company,entity);
            entity.setInGoodsId(inGoods.getId());
            entity.setRefundNumber(new BigDecimal(0));
            if(!PdosUtils.inTaxRateFlag(businessSet)) {
                entity.setTax(new BigDecimal(0));
            } else {
                entity.setTax(entity.getAmount().multiply(PdosUtils.inTaxRate(businessSet)));
            }
            inGoodsGoodsList.add(entity);

            if (!Utils.isEmpty(vo.getGoodsSnList())){
                for (GoodsSn goodsSn : vo.getGoodsSnList()) {
                    DataUtil.processEntity(company, goodsSn,snInitMap);
                    goodsSnList.add(goodsSn);

                    GoodsSnLog log = new GoodsSnLog();
                    DataUtil.processEntity(company,log);
                    log.setGoodsId(goodsSn.getGoodsId());
                    log.setSn(goodsSn.getSn());
                    log.setType(1);
                    log.setInGoodsGoodsId(entity.getId());
                    if (!Utils.isEmpty(inGoods.getBorrowInId())) {
                        log.setBorrow(1);
                    }
                    goodsSnLogList.add(log);
                }
            }
        }



        inGoodsService.insert(businessSet, inGoods,inGoodsGoodsList, goodsSnList,goodsSnLogList);

        if (!Utils.isEmpty(goodsSnList) && PdosUtils.houseInOut(businessSet) && Utils.isEmpty(inGoods.getBorrowInId())) {
            //已启用待出库入管理，但是前台传入了sn号，提示
            return ResponseEntity.success("处理成功，管理员在您新增单据过程中启用了出入库管理，录入的sn需要在入库时录入");
        }
        return ResponseEntity.success();

    }

    @ResponseBody
    @RequiresPermissions("inGoods:close")
    @RequestMapping("/inGoods/close")
    public ResponseEntity close(@RequestBody InGoods inGoods){
        //检查是否已经关闭
        if (inGoodsService.checkClose(inGoods)){
            return ResponseEntity.fail("该单据已被关闭，不能重复关闭");
        }


        if(inGoodsService.getById(inGoods.getId()).getRefund() !=0) {
            return ResponseEntity.fail("该进货单有退货，建议在作废退货单后才允许作废该进货单。");
        }

        if(houseInService.checkByLinkId(inGoods.getId())) {
            return ResponseEntity.fail("该订单存在入库单，请先作废对应的入库单");
        }

        try {
            inGoodsService.close(inGoods, getBusinessSet());
            return ResponseEntity.success();
        }catch (Exception e) {
            return ResponseEntity.fail("关闭订单失败");
        }
    }


    @ResponseBody
    @RequiresPermissions("inGoods:insert")
    @RequestMapping("/inGoods/updateImage")
    public ResponseEntity updateImage(@RequestBody InGoods inGoods){
        try {
            InGoods temp = new InGoods();
            temp.setId(inGoods.getId());
            temp.setImage(inGoods.getImage());
            inGoodsService.updateById(temp);
            return ResponseEntity.success();
        }catch (Exception e) {
            return ResponseEntity.fail("更新图片失败");
        }
    }

    @ResponseBody
    @RequestMapping(value = "/inGoods/uploadImg", method = RequestMethod.POST)
    public ResponseData uploadImg(MultipartFile imageFile) {
        return processUploadImg(imageFile, "inGoods");
    }


    @ResponseBody
    @RequestMapping("/inGoods/getVoById")
    public ResponseData getVoById(String id) {
        return ResponseData.success(inGoodsService.getVoById(id));
    }


    /**
     * 根据获取InGoodsVo，若其实由入库单入库，则要获取已入库商品的数量
     * @param id
     * @return
     */
    @ResponseBody
    @RequestMapping("/inGoods/getVoByIdWithCanRefundNumber")
    public ResponseData getVoByIdWithCanRefundNumber(String id) {
        InGoodsVo inGoodsVo = inGoodsService.getVoById(id);
        if (inGoodsVo == null) {
            return ResponseData.fail("未找到单据");
        }

        //获取到此进货单的已经入库的数量
        if (inGoodsVo.getStatus() != 1) {
            //由入库单入库的，需要取得该进货的每个商品的入库数量
            List<HouseInGoods> houseInGoodsList = houseInGoodsService.listByLinkId(id);
            Map<String, BigDecimal> houseInMap = new HashMap<>();//key-goodsId value-number
            for (HouseInGoods houseInGoods : houseInGoodsList) {
                String inGoodsGoodsId = houseInGoods.getInGoodsGoodsId();
                BigDecimal number = houseInGoods.getNumber();
                if (houseInMap.containsKey(inGoodsGoodsId)) {
                    //若存在，则累加数量
                    houseInMap.put(inGoodsGoodsId, houseInMap.get(inGoodsGoodsId).add(number));
                } else {
                    //不存在，则新建
                    houseInMap.put(inGoodsGoodsId, number);
                }
            }

            //新组成的数据
            List<InGoodsGoodsVo> inGoodsGoodsVoList = new ArrayList<>();
            for (InGoodsGoodsVo vo : inGoodsVo.getInGoodsGoodsVoList()) {
                if (houseInMap.containsKey(vo.getId())) {
                    //将已存在进货单对应入库单的商品添加到新表，并将数量重新赋值
                    vo.setNumber(houseInMap.get(vo.getId()));
                    vo.setAmount(vo.getNumber().multiply(vo.getPrice()));//重新计算器总额
                    inGoodsGoodsVoList.add(vo);
                }
            }
            inGoodsVo.setInGoodsGoodsVoList(inGoodsGoodsVoList);
        }

        return ResponseData.success(inGoodsVo);
    }

    @ResponseBody
    @RequestMapping("/inGoods/listVoByInGoodsOrder")
    public ResponseData listVoByInGoodsOrder(String inGoodsOrderId) {
        return ResponseData.success(inGoodsService.listVoByInGoodsOrder(inGoodsOrderId));
    }

    @ResponseBody
    @RequestMapping("/inGoods/listVoByBorrowIn")
    public ResponseData listVoByBorrowIn(String borrowInId) {
        return ResponseData.success(inGoodsService.listVoByBorrowInId(borrowInId));
    }


    @ResponseBody
    @RequiresPermissions("inGoods:export")
    @RequestMapping("/inGoods/export")
    public ResponseData export(String close,
                               String search,
                               String no,
                               String goodsName,
                               String remark,
                               String provider,
                               String makeTime1,
                               String makeTime2,
                               String storeId,
                               String userId,
                               String date1,
                               String date2,
                               String date,
                               String providerId,
                               String houseId,
                               String makeUserId){
        Company company = getCompany();
        UserVo userVo = getLoginUserVo();

        List<InGoodsVo> list = inGoodsService.listVo(company.getId(),
                null,
                null,
                Utils.genBoolean(close),
                Utils.genLikeData(search),
                Utils.genLikeData(no),
                Utils.genLikeData(goodsName),
                Utils.genLikeData(remark),
                Utils.genLikeData(provider),
                Utils.genDate(makeTime1),
                Utils.genDate(makeTime2),
                storeId,
                PdosUtils.getViewOrderStoreId(userVo,null),
                PdosUtils.getViewOrderUserId(userVo,userId),
                Utils.genDate(date1),
                Utils.genDate(date2),
                Utils.genDate(date),
                providerId,
                houseId,
                makeUserId);

        String fileName = "进货单列表" + DateUtils.getDate(new Date(), DateUtils.YYYYMMDDHHMMSSSS) + ".xlsx";
        try {
            String path = FileProperUtil.getInstance().getVal("excel.temp");
            OutputStream out = new FileOutputStream(path+fileName);
            ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX,true);
            Sheet sheet1 = new Sheet(1,0, ExcelInGoods.class);
            sheet1.setSheetName("进货单信息");
            writer.write(genExcelInGoodsList(list), sheet1);
            writer.finish();
            out.close();
            CleanTempExcelTask.put(fileName,new Date().getTime());
            return ResponseData.success(fileName);
        } catch (IOException e) {
            return ResponseData.fail("订单列表导出失败");
        }
    }

    private List<ExcelInGoods> genExcelInGoodsList(List<InGoodsVo> inGoodsVoList) {
        List<ExcelInGoods> list = new ArrayList<>();
        BusinessSet businessSet = getBusinessSet();
        for (InGoodsVo vo : inGoodsVoList){
            ExcelInGoods excel = new ExcelInGoods();
            excel.setDate(DateUtils.getDate(vo.getDate(), DateUtils.YYYY_MM_DD));
            excel.setNo(vo.getNo());

            excel.setProviderNo(vo.getProvider().getNo());
            excel.setProvider(vo.getProvider().getName());
            String goods = "";
            BigDecimal number = new BigDecimal("0");
            for (InGoodsGoodsVo inGoodsGoodsVo : vo.getInGoodsGoodsVoList()){
                number = number.add(inGoodsGoodsVo.getNumber());
                goods += inGoodsGoodsVo.getGoodsVo().getName() + "、";
            }
            excel.setGoods(goods);
            excel.setNumber(PdosUtils.getNumber(number,businessSet));
            excel.setTotalAmt(PdosUtils.getPrice(vo.getTotalAmt(),businessSet));
            excel.setRealAmt(PdosUtils.getPrice(vo.getRealAmt(),businessSet));
            excel.setStore(vo.getHouseVo().getStore().getName());
            excel.setHouse(vo.getHouseVo().getName());
            excel.setUser(vo.getUser().getName());
            excel.setMakeUser(vo.getMakeUser().getName());
            excel.setRemark(vo.getRemark());
            excel.setClose(vo.getClose() ? "是":"否");
            list.add(excel);
        }
        return list;
    }

}
